package main

import "fmt"

func main() {
	fmt.Println("数据库已连接")
	defer closeDB()
	defer fmt.Println(returnString())
	fmt.Println("执行数据库查询...")
	// panic("不小心写错了SQL语句...")
	// fmt.Println("Unreachable code")

	//defer 关键字后面的表达式，是在将 deferred 函数注册到deferred 函数栈的时候进行求值的
	fmt.Print("testA result:")
	testA()
	println()
	fmt.Print("testB result:")
	testB()
	println()
	fmt.Print("testC result:")
	testC()
	println()
}

func closeDB() {
	fmt.Println("数据库连接已关闭")
}
func returnString() string {
	return "返回一个字符串"
}

func testA() {
	for i := 0; i <= 3; i++ {
		defer fmt.Print(i, " ")
	}
	//输出 testA result:3 2 1 0
	/*每当 defer 将fmt.Print 注册到 deferred 函数栈的时候，都会对 Print 后面的参数进行求值。依次压入 deferred 函数栈的函数是：
	fmt.Print(0)
	fmt.Print(1)
	fmt.Print(2)
	fmt.Print(3)
	因此，当 testA 返回后，deferred 函数被调度执行时，上述压入栈的 deferred 函数将以LIFO 次序出栈执行，这时的输出的结果为：3,2,1,0
	*/
}
func testB() {
	for i := 0; i <= 3; i++ {
		defer func(n int) {
			fmt.Print(n, " ")
		}(i)
	}
	//输出 testB result:3 2 1 0
	/*每当 defer 将匿名函数注册到 deferred 函数栈的时候，都会对该匿名函数的参数进行求值。依次压入 deferred 函数栈的函数是：
	func(0)
	func(1)
	func(2)
	func(3)
	因此，当 testB 返回后，deferred 函数被调度执行时，上述压入栈的 deferred 函数将以LIFO 次序出栈执行，因此输出的结果为：3,2,1,0
	*/
}
func testC() {
	for i := 0; i <= 3; i++ {
		defer func() {
			fmt.Print(i, " ")
		}()
	}

	//输出 testC result:4 4 4 4
	/* testC 中 defer 后面接的是一个不带参数的匿名函数。依次压入 deferred 函数栈的函数是：
	func()
	func()
	func()
	func()
	所以，当 testC 返回后，deferred 函数被调度执行时，上述压入栈的 deferred 函数将以LIFO 次序出栈执行。
	匿名函数会以闭包的方式访问外围函数的变量 i，并通过 Print 输出i 的值，此时 i 的值为 4，因此 testC 的输出结果为：4,4,4,4
	*/
}

func testDeferUse() {
	/*
		var c chan int
		var sl []int
		var m = make(map[string]int, 10)
		m["item1"] = 1
		m["item2"] = 2
		var a = complex(1.0, -1.4)
		var sl1 []int
		defer append(sl, 11)
		defer cap(sl)
		defer close(c)
		defer complex(2, -2)
		defer copy(sl1, sl)
		defer delete(m, "item2")
		defer imag(a)
		defer len(sl)
		defer make([]int, 10)
		defer new(*int)
		defer panic(1)
		defer print("hello, defer\n")
		defer println("hello, defer")
		defer real(a)
		defer recover()
	*/

	/*
		./func_defer.go:29:8: defer discards result of append(sl, 11) (value of type []int)
		./func_defer.go:30:8: defer discards result of cap(sl) (value of type int)
		./func_defer.go:32:8: defer discards result of complex(2, -2) (untyped complex constant (2 + -2i))
		./func_defer.go:35:8: defer discards result of imag(a) (value of type float64)
		./func_defer.go:36:8: defer discards result of len(sl) (value of type int)
		./func_defer.go:37:8: defer discards result of make([]int, 10) (value of type []int)
		./func_defer.go:38:8: defer discards result of new(*int) (value of type **int)
		./func_defer.go:42:8: defer discards result of real(a) (value of type float64)
	*/

	//对于不能直接作为 deferred 函数的内置函数，可以使用一个包裹它的匿名函数来间接实现
	var slx []int
	defer func() {
		_ = append(slx, 11)
	}()
}
